#ifndef _J_LISTE_H_
#define _J_LISTE_H_

/* par macroa za rad s listom

  'lista' i 'elem' su kazaljke na strukture koje moraju imati:
	'lista': *prvi i *zadnji
	'elem': *iduci
  npr.
	struct nesto1 {
		...
		struct nesto2 *prvi;
		struct nesto2 *zadnji;
		...
	} *lista;
	
	struct nesto2 {
		...
		struct nesto2 *iduci;
		...
	} *elem;
*/

#define UZMI_PRVI_ELEMENT(lista)					\
({									\
	typeof(lista) l = (lista);					\
	typeof((lista)->prvi) e = l->prvi;				\
									\
	if (e != NULL) /* nije prazna */				\
		l->prvi = e->iduci;					\
									\
	e;								\
})
//koristenje: a = UZMI_PRVI_ELEMENT(&neka_lista);

//ne brise element iz liste
#define POGLEDAJ_PRVI_ELEMENT(lista)	((lista)->prvi)
//koristenje: a = POGLEDAJ_PRVI_ELEMENT(&neka_lista);

#define POGLEDAJ_IDUCI_ELEMENT(elem)	((elem)->iduci)
//koristenje: a = POGLEDAJ_IDUCI_ELEMENT(&neki_elem);

#define MAKNI_IZ_LISTE(lista, elem)					\
({									\
	typeof(lista) l = (lista);					\
	typeof(elem) e = (elem), pom;					\
	bool nasao = NEISTINA;						\
									\
	if (l->prvi == e) {						\
		l->prvi = e->iduci;					\
		nasao = ISTINA;						\
	}								\
	else {								\
		pom = l->prvi;						\
		while (pom->iduci != NULL) {				\
			if (pom->iduci == e) {				\
				pom->iduci = e->iduci;			\
				if (l->zadnji == e)			\
					l->zadnji = pom;		\
				nasao = ISTINA;				\
				break;					\
			}						\
			pom = pom->iduci;				\
		}							\
	}								\
									\
	nasao;								\
})
//koristenje: maknuo = MAKNI_IZ_LISTE(&neka_lista, &element);

#define DODAJ_NA_KRAJ(lista, elem)					\
{									\
	typeof(lista) l = (lista);					\
	typeof(elem) e = (elem);					\
									\
	if (l->prvi == NULL) {						\
		l->prvi = l->zadnji = e;				\
	}								\
	else {								\
		l->zadnji->iduci = e;					\
		l->zadnji = e;						\
	}								\
	e->iduci = NULL;						\
}
//koristenje: DODAJ_NA_KRAJ(&neka_lista, &element);

#define DODAJ_NA_POCETAK(lista, elem)					\
{									\
	typeof(lista) l = (lista);					\
	typeof(elem) e = (elem);					\
									\
	e->iduci = l->prvi;						\
	l->prvi = e;							\
									\
	if (e->iduci == NULL) {						\
		l->zadnji = e;						\
	}								\
}
//koristenje: DODAJ_NA_POCETAK(&neka_lista, &element);

#define DODAJ_U_SORT_LISTU(lista, elem, usporedi)			\
{									\
	typeof(lista) l = (lista);					\
	typeof(elem) e = (elem), p;					\
									\
	if (l->prvi == NULL) {						\
		l->prvi = l->zadnji = e;				\
		e->iduci = NULL;					\
	}								\
	else {								\
		if (usporedi(e, l->prvi) < 0) {				\
			e->iduci = l->prvi;				\
			l->prvi = e;					\
		}							\
		else {							\
			p = l->prvi;					\
			while (p->iduci && usporedi(e, p->iduci) >= 0)	\
				p = p->iduci;				\
									\
			e->iduci = p->iduci;				\
			p->iduci = e;					\
									\
			if (e->iduci == NULL)				\
				l->zadnji = e;				\
		}							\
	}								\
}
//koristenje: DODAJ_U_SORT_LISTU(&neka_lista, &element, funkcija_usporedbe);
//'funkcija_usporedbe' mora znati usporedjivati objekte tipa 'element'-a
//i vracati <0 kad je a < b, =0 za a == b, te >0 za a > b
//sortiranje ide od manjeg prema vecem, ako je ovako - za suprotno treba dati
//suprotne uvjete


#include "razno.h"

#define DOHVATI(POLJE)							\
({									\
	int id = -1;							\
									\
	id = PRVI_SLOBODNI(POLJE);					\
									\
	if (id != -1)							\
		OZNACI_ZAUZETO(POLJE, id);				\
									\
	id;								\
})

#define OBRISI(POLJE, ID)						\
({									\
	int povr = 0, n = BR_ELEM_POLJA(POLJE);				\
									\
	if (ID < 0 || ID >= n || PROVJERI_SLOBODNO(POLJE, ID))		\
		povr = -1;						\
	else								\
		OZNACI_SLOBODNO(POLJE, ID);				\
									\
	povr;								\
})

#endif	/* _J_LISTE_H_ */
